#include "rational.h"

Rational::Rational(int inpNumerator, int inpDenominator): numerator(inpNumerator), denominator(inpDenominator){
    this->simplify();
}

Rational::~Rational(){}

const int& Rational::GetNumerator() const{
    return this->numerator;
}

const int& Rational::GetDenomiantor() const{
    return this->denominator;
}

Rational::Rational(const Rational& r){
    this->numerator = r.GetNumerator();
    this->denominator = r.GetDenomiantor();
}

void Rational::Swap(Rational& r){
    std::swap(this->numerator, r.numerator);
    std::swap(this->denominator, r.denominator);
}

int Rational::GetGCD(int a, int b) const{
    int c;
    while(1)
    {
        c = a%b;
        if(c==0)
            return b;
        a = b;
        b = c;
    }
}

void Rational::simplify(){
    int gcd = GetGCD(std::abs(this->GetNumerator()), std::abs(this->GetDenomiantor()));
    this->numerator /= gcd;
    this->denominator /= gcd;
}

Rational& Rational::operator= (const Rational& r){
    Rational tmp(r);
    this->Swap(tmp);
    return *this;
}

Rational& Rational::operator+= (const Rational& r){
    this->numerator = this->GetNumerator() * r.GetDenomiantor() + r.GetNumerator() * this->GetDenomiantor();
    this->denominator *= r.GetDenomiantor();
    this->simplify();
    return *this;
}

Rational& Rational::operator-= (const Rational& r){
    this->numerator = this->GetNumerator() * r.GetDenomiantor() - r.GetNumerator() * this->GetDenomiantor();
    this->denominator *= r.GetDenomiantor();
    this->simplify();
    return *this;
}

Rational& Rational::operator*= (const Rational& r){
    this->numerator *= r.GetNumerator();
    this->denominator *= r.GetDenomiantor();
    this->simplify();
    return *this;
}

Rational& Rational::operator/= (const Rational& r){
    *this *= Rational(r.GetDenomiantor(), r.GetNumerator());
    return *this;
}

Rational& Rational::operator++(){
    *this += Rational(1,1);
    return *this;
}

Rational Rational::operator++(int){
    Rational tmp(*this);
    ++(*this);
    return tmp;
}

Rational& Rational::operator--(){
    *this -= Rational(1,1);
    return *this;
}

Rational Rational::operator--(int){
    Rational tmp(*this);
    --(*this);
    return tmp;
}

Rational::operator double () const{
    return (double)this->GetNumerator() / (double)this->GetDenomiantor();
}

Rational operator+ (const Rational& a, const Rational& b){
    Rational tmp(a);
    tmp += b;
    return tmp;
}

Rational operator- (const Rational& a, const Rational& b){
    Rational tmp(a);
    tmp -= b;
    return tmp;
}

Rational operator* (const Rational& a, const Rational& b){
    Rational tmp(a);
    tmp *= b;
    return tmp;
}

Rational operator/ (const Rational& a, const Rational& b){
    Rational tmp(a);
    tmp /= b;
    return tmp;
}

bool operator== (const Rational& a, const Rational& b){
    return a.GetNumerator() == b.GetNumerator() && a.GetDenomiantor() == b.GetDenomiantor();
}

bool operator!= (const Rational& a, const Rational& b){
    return !(a == b);
}

bool operator<= (const Rational& a, const Rational& b){
    return !(a > b);
}

bool operator>= (const Rational& a, const Rational& b){
    return !(a < b);
}

bool operator<  (const Rational& a, const Rational& b){
    return a.GetNumerator() * b.GetDenomiantor() < a.GetDenomiantor() * b.GetNumerator();
}

bool operator>  (const Rational& a, const Rational& b){
    return a.GetNumerator() * b.GetDenomiantor() > a.GetDenomiantor() * b.GetNumerator();
}

ostream& operator<<(ostream& oout, const Rational& r){
    oout<<r.GetNumerator()<<"/"<<r.GetDenomiantor();
    return oout;
}